package com.magiccompass.alipay.barcode.controller;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.TreeMap;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.magiccompass.alipay.barcode.constants.AlipayPartnerConstants;
import com.magiccompass.alipay.barcode.constants.BusinessLogicConstants;
import com.magiccompass.alipay.barcode.entity.AlipayQRCodeNotification;
import com.magiccompass.alipay.barcode.entity.AlipayQRCodeTransaction;
import com.magiccompass.alipay.barcode.entity.MerchantInfo;
import com.magiccompass.alipay.barcode.entity.MerchantTransaction;
import com.magiccompass.alipay.barcode.pageform.AlipayQRCodeNotificationPageForm;
import com.magiccompass.alipay.barcode.service.AlipayBarcodeService;
import com.magiccompass.alipay.barcode.signature.MD5Signature;
import com.magiccompass.alipay.barcode.signature.MD5SignatureValidation;
import com.magiccompass.alipay.barcode.signature.RSASignatureValidation;
import com.magiccompass.alipay.barcode.util.AlipayQRCodeNotificationUtil;
import com.magiccompass.alipay.barcode.util.DateTimeUtil;
import com.magiccompass.alipay.barcode.util.SimpleJsonUtil;

@Controller
@RequestMapping(value="/alipayNotification")
public class AlipayQRCodeNotificationController {
	static Logger logger = LogManager.getLogger(AlipayQRCodeNotificationController.class.getName());
	@Resource(name="alipayBarcodeService")
	private AlipayBarcodeService alipayBarcodeService;
	
	private MerchantInfo mi;
	
	@RequestMapping(value="/notify", method = {RequestMethod.GET,RequestMethod.POST})
    public String notify(@ModelAttribute("alipayQRCodeNotificationPageForm") AlipayQRCodeNotificationPageForm qrfm,Model model,HttpServletRequest request) {
		String returnStr = "common/success";
		//System.out.println("_-=-=-=-=-=-= Now receiving Alipay notification, Notify_id:"+qrfm.getNotify_id());
		logger.info("_-=-=-=-=-=-= Now receiving Alipay notification, Notify_id:"+qrfm.getNotify_id());
		try {
			if(qrfm.getNotify_id() != null){
				if(isDuplicateTransaction(qrfm)){
					return returnStr;
				}else{
					saveAlipayNotificationEntity(qrfm);
					//if(testSign(qrfm)){
					testSign(qrfm);
					{
						switch(qrfm.getNotify_action_type()){
							case "createDirectPayTradeByBuyerAction":
								handleCreate(qrfm);
								break;
							case "payByAccountAction":
								handlePay(qrfm);
								break;
							case "refundFPAction":
								handleRefund(qrfm);
								break;
							case "reverseAction":
								handleReverse(qrfm);
								break;
							case "closeTradeAction":
								handleClose(qrfm);
								break;
							case "finishFPAction":
								handleFinish(qrfm);
								break;
						} // switch					
					}//if(testSign(qrfm)){
				}//if(isDuplicatePayedTransaction(qrfm)){}else{
			}//if(qrfm.getNotify_id() != null){
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return returnStr;
    }
	
	private boolean testSign(AlipayQRCodeNotificationPageForm qrfm){
		boolean returnFlag = false;
		TreeMap<String,String> notificationMap = AlipayQRCodeNotificationUtil.notificationPageForm2Map(qrfm);
		try {
			String signType = qrfm.getSign_type();
			if("MD5".equals(signType)){
				returnFlag = MD5SignatureValidation.md5Check(notificationMap);
			}else if("RSA".equals(signType)){
				returnFlag = RSASignatureValidation.rsaCheck(notificationMap, AlipayPartnerConstants.ALIPAY_PUBLIC_KEY, AlipayPartnerConstants._INPUT_CHAR_SET);
			}else{
				System.out.println("-=-=-=- Unsupport sign type happened. Notify_id:"+qrfm.getNotify_id());
				logger.info("-=-=-=- Unsupport sign type happened. Notify_id:"+qrfm.getNotify_id());
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return returnFlag;
	}
	
	private void saveAlipayNotificationEntity(AlipayQRCodeNotificationPageForm qrfm){
		AlipayQRCodeNotification aqrcn = AlipayQRCodeNotificationUtil.notificationPageForm2Entity(qrfm);
		alipayBarcodeService.save(aqrcn);
	}
	
	private boolean isDuplicateTransaction(AlipayQRCodeNotificationPageForm qrfm){
		AlipayQRCodeNotification aqrcn = alipayBarcodeService.findAlipayQRCodeNotificationByNotifyId(qrfm.getNotify_id());
		return (aqrcn != null)?true:false;
	}
	
	private void handleCreate(AlipayQRCodeNotificationPageForm qrfm){
		//TODO
		logger.info("-=-=-= Unhandled create notify, id:"+qrfm.getNotify_id());
	}
	private void handlePay(AlipayQRCodeNotificationPageForm qrfm){
		//logger.info("-=-=-= In handlePay-=-=-=-= notify_id:"+qrfm.getNotify_id()+", trade_status:"+qrfm.getTrade_status());
		if("TRADE_SUCCESS".equals(qrfm.getTrade_status())){
			if(makeSuccessTransaction(qrfm)){
				AlipayQRCodeNotificationUtil.sendMechantMTSuccessEmail(mi, qrfm);
			}
		}
	}
	private boolean makeSuccessTransaction(AlipayQRCodeNotificationPageForm qrfm){
		boolean returnValue = false;
		try {
			MerchantTransaction mt = new MerchantTransaction();
			mt.setCreateBy(BusinessLogicConstants.SYSTEM_CREATOR_ID);
			MerchantInfo mi = getMerchantByQRCode(qrfm.getExtra_common_param());
			mt.setMerchant(mi);
			mt.setStatus("S");
			BigDecimal bd = new BigDecimal(qrfm.getTrans_amount());
			bd.setScale(2, RoundingMode.HALF_UP);
			mt.setTotalAmount(bd);
			mt.setType("Q");
			mt.setUpdateby(BusinessLogicConstants.SYSTEM_CREATOR_ID);
			mt.setUpdateTime(DateTimeUtil.getCurrentTimestamp());
			alipayBarcodeService.save(mt);
			
			AlipayQRCodeTransaction aqrct = new AlipayQRCodeTransaction();
			aqrct.setMt(mt);
			aqrct.setQrCodeNotification(alipayBarcodeService.findAlipayQRCodeNotificationByNotifyId(qrfm.getNotify_id()));
			alipayBarcodeService.save(aqrct);
			returnValue = true;
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return returnValue;
	}
	private MerchantInfo getMerchantByQRCode(String merchantQRCodeInJson){
		String merchantQRCode = SimpleJsonUtil.getQRCodeValue(merchantQRCodeInJson);
		mi = alipayBarcodeService.findMerchantByAlipayQRCode(merchantQRCode);
		return mi;
	}
	private void handleRefund(AlipayQRCodeNotificationPageForm qrfm){
		//TODO
		logger.info("-=-=-= Unhandled refund notify, id:"+qrfm.getNotify_id());
	}
	private void handleReverse(AlipayQRCodeNotificationPageForm qrfm){
		//TODO
		logger.info("-=-=-= Unhandled reverse notify, id:"+qrfm.getNotify_id());
	}
	private void handleClose(AlipayQRCodeNotificationPageForm qrfm){
		//TODO
		logger.info("-=-=-= Unhandled close notify, id:"+qrfm.getNotify_id());
	}
	private void handleFinish(AlipayQRCodeNotificationPageForm qrfm){
		//TODO
		logger.info("-=-=-= Unhandled finish notify, id:"+qrfm.getNotify_id());
	}
	
	@RequestMapping(value="/nTest", method = {RequestMethod.GET,RequestMethod.POST})
	public String nTest(@ModelAttribute("alipayQRCodeNotificationPageForm") AlipayQRCodeNotificationPageForm qrfm,Model model,HttpServletRequest request) {
		String returnStr = "common/nTest";
		qrfm.setBody("Hello");
		qrfm.setBuyer_email("13882390011");
		qrfm.setBuyer_id("2088102105236945");
		qrfm.setCurrency("USD");
		qrfm.setExtra_common_param("{\"qrcode\":\"https://qr.alipay.com/ocx02489wk8syu4wdrwl4e7\"}");
		qrfm.setForex_rate("6.0939");
		qrfm.setForex_total_fee("0.31");
		qrfm.setGmt_create("2016-05-18 11:45:57");
		qrfm.setGmt_payment("2016-05-18 11:46:57");
		qrfm.setNotify_action_type("payByAccountAction");
		qrfm.setNotify_id("ac05099524730693a8b330c5ecf72da978");
		qrfm.setNotify_time("2016-05-18 11:49:57");
		qrfm.setNotify_type("trade_status_sync");
		//qrfm.setOut_biz_no(out_biz_no);
		//qrfm.setOut_trade_no(out_trade_no);
		qrfm.setPaytools_pay_amount("[{\"MCARD\":\"7.94\"},{\"TMPOINT\":\"1.69\"},{\"BANKCARD\":\"5.55\"}]");
		qrfm.setPrice("1.97");
		qrfm.setQuantity("1");
		qrfm.setRefund_fee("1.00");
		qrfm.setSeller_email("zhuzhanghu@alitest.com");
		qrfm.setSeller_id("2088101106499364");
		qrfm.setSign_type("MD5");
		qrfm.setSubject("Sound wave payment- Subsidiary account-sky");
		qrfm.setTotal_fee("1.97");
		qrfm.setTrade_no("2013112711001004940000394507");
		qrfm.setTrade_status("TRADE_SUCCESS");
		qrfm.setTrans_amount("10.00");
		qrfm.setTrans_currency("TWD");
		qrfm.setTrans_forex_rate("0.0312");
		
		TreeMap<String,String> notificationMap = AlipayQRCodeNotificationUtil.notificationPageForm2Map(qrfm);
		String signContent = MD5SignatureValidation.getSignCheckContent(notificationMap);
		try {
			String sign = MD5Signature.getMD5String(signContent);
			
			qrfm.setSign(sign);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return returnStr;
	}
	
	public static void main(String[] args){
		AlipayQRCodeNotificationController a = new AlipayQRCodeNotificationController();
		AlipayQRCodeNotificationPageForm qrfm = new AlipayQRCodeNotificationPageForm();
		qrfm.setBuyer_email("sunhaijun@hotmail.com");
		qrfm.setBuyer_id("2088002002892098");
		qrfm.setCurrency("NZD");
		qrfm.setExtra_common_param("{\"qrcode\":\"https://qr.alipay.com/ocx05201iiiauheal7uk92c\"}");
		qrfm.setForex_rate("4.45120000");
		//qrfm.setForex_total_fee("0.31");
		qrfm.setGmt_create("2016-05-19 09:01:01");
		qrfm.setGmt_payment("2016-05-19 09:01:05");
		qrfm.setNotify_action_type("payByAccountAction");
		qrfm.setNotify_id("13c7cd512e14e012e2d39c2b0550969gp2");
		qrfm.setNotify_time("2016-05-19 09:01:05");
		qrfm.setNotify_type("trade_status_sync");
		//qrfm.setOut_biz_no(out_biz_no);
		qrfm.setOut_trade_no("0020028920981463619661407");
		qrfm.setPaytools_pay_amount("[{\"ALIPAYACCOUNT\":\"0.36\"}]");
		qrfm.setPrice("0.36");
		qrfm.setQuantity("1");
		//qrfm.setRefund_fee("1.00");
		qrfm.setSeller_email("tim@magiccompass.com");
		qrfm.setSeller_id("2088221411747939");
		qrfm.setSign("067daf443049c91552d16f77494f81b5");
		qrfm.setSign_type("MD5");
		qrfm.setSubject("MC Test 03");
		qrfm.setTotal_fee("0.36");
		qrfm.setTrade_no("2016051921001004090216395500");
		qrfm.setTrade_status("TRADE_SUCCESS");
		qrfm.setTrans_amount("0.08");
		qrfm.setTrans_currency("NZD");
		//qrfm.setTrans_forex_rate("0.0312");
		a.testSign(qrfm);
	}
}